package org.qpcr.community.auth.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryOperation;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
import org.hswebframework.web.authorization.annotation.*;
import org.hswebframework.web.crud.query.QueryHelper;
import org.hswebframework.web.crud.service.ReactiveCrudService;
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
import org.hswebframework.web.exception.ValidationException;
import org.hswebframework.web.i18n.LocaleUtils;
import org.qpcr.community.auth.entity.OrganizationEntity;
import org.qpcr.community.auth.entity.RoleGroupEntity;
import org.qpcr.community.auth.service.OrganizationService;
import org.qpcr.community.web.response.ValidationResult;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.UUID;

@RequestMapping("/organization")
@RestController
@Resource(id = "organization", name = "部门管理")
@Tag(name = "部门管理")
public class OrganizationController implements ReactiveServiceCrudController<OrganizationEntity, String> {

    private final OrganizationService organizationService;

    private final QueryHelper queryHelper;

    public OrganizationController(OrganizationService organizationService, QueryHelper queryHelper) {
        this.organizationService = organizationService;
        this.queryHelper = queryHelper;
    }

    private Flux<OrganizationEntity> queryAll() {
        return organizationService.createQuery().fetch();
    }

    private Flux<OrganizationEntity> queryAll(Mono<QueryParamEntity> queryParamEntity) {
        return organizationService.query(queryParamEntity);
    }

    @PostMapping("/add")
    @SaveAction
    @Operation(
        summary = "新增"
    )
    @Authorize(ignore = true)
    public Mono<SaveResult> addOverride(@RequestBody Flux<OrganizationEntity> payload) {

        return this.save(payload
                             .map(org -> {
                                 // 修改实体
                                 if (org.getKey() == null) {
                                     org.setKey(UUID.randomUUID().toString());
                                 }
                                 return org;
                             }));
    };



    @GetMapping("/_all/tree")
    @Authorize(merge = false)
    @Operation(summary = "获取全部机构信息(树结构)")
    public Flux<OrganizationEntity> getAllOrgTree() {
        return queryAll()
            .collectList()
            .flatMapIterable(list -> TreeSupportEntity.list2tree(list, OrganizationEntity::setChildren));
    }

    @PostMapping("/_all/tree")
    @Authorize(merge = false)
    @Operation(summary = "获取全部机构信息(树结构)")
    public Flux<OrganizationEntity> getAllOrgTree(@RequestBody Mono<QueryParamEntity> query) {
        return queryAll(query)
            .collectList()
            .flatMapIterable(list -> TreeSupportEntity.list2tree(list, OrganizationEntity::setChildren));
    }

    @GetMapping("/_all")
    @Authorize(merge = false)
    @Operation(summary = "获取全部机构信息")
    public Flux<OrganizationEntity> getAllOrg() {
        return queryAll();
    }

    @PostMapping("/_all")
    @Authorize(merge = false)
    @Operation(summary = "获取全部机构信息")
    public Flux<OrganizationEntity> getAllOrg(@RequestBody Mono<QueryParamEntity> query) {
        return queryAll(query);
    }

    @GetMapping("/_query/_children/tree")
    @QueryAction
    @QueryOperation(summary = "查询机构列表(包含子机构)树结构")
    public Mono<List<OrganizationEntity>> queryChildrenTree(@Parameter(hidden = true) QueryParamEntity entity) {
        return organizationService.queryIncludeChildrenTree(entity);
    }

    @GetMapping("/_query/_children")
    @QueryAction
    @QueryOperation(summary = "查询机构列表(包含子机构)")
    public Flux<OrganizationEntity> queryChildren(@Parameter(hidden = true) QueryParamEntity entity) {
        return organizationService.queryIncludeChildren(entity);
    }

    @PostMapping("/{id}/users/_bind")
    @ResourceAction(id = "bind-user", name = "绑定用户")
    @Operation(summary = "绑定用户到机构")
    public Mono<Integer> bindUser(@Parameter(description = "机构ID") @PathVariable String id,
                                  @Parameter(description = "用户ID")
                                  @RequestBody Mono<List<String>> userId) {

        return userId.flatMap(list -> organizationService.bindUser(id, list));

    }

    @PostMapping("/{id}/users/_unbind")
    @ResourceAction(id = "unbind-user", name = "解绑用户")
    @Operation(summary = "从机构解绑用户")
    public Mono<Integer> unbindUser(@Parameter(description = "机构ID") @PathVariable String id,
                                    @Parameter(description = "用户ID")
                                    @RequestBody Mono<List<String>> userId) {
        return userId.flatMap(list -> organizationService.unbindUser(id, list));
    }

    @Override
    public ReactiveCrudService<OrganizationEntity, String> getService() {
        return organizationService;
    }


    @PostMapping("/_query/unitList")
    @Authorize(ignore = true)
    @Operation(summary = "获取单位列表")
    public Flux<OrganizationEntity> getAllOrgList(@RequestBody Mono<QueryParamEntity> query) {
        return queryAll(query);
    }

    @PostMapping("/_validate")
    @Authorize(merge = false)
    @Operation(summary = "组织名称验证")
    public Mono<ValidationResult> orgNameValidate(@RequestBody(required = true) OrganizationEntity orgEntity) {

        if(orgEntity.getId()!=null && orgEntity.getId().isEmpty()){
            return LocaleUtils
                .currentReactive()
                .flatMap(locale -> {
                    return organizationService.findByname(orgEntity.getName())
                                           .map(i -> ValidationResult.error(LocaleUtils.resolveMessage(
                                               "error.orgname_already_exist",
                                               locale,
                                               "单位名称" + orgEntity.getName() + "已存在", orgEntity.getName() ))
                                           );
                })
                .defaultIfEmpty(ValidationResult.success())
                .onErrorResume(ValidationException.class,
                               e -> e.getLocalizedMessageReactive().map(ValidationResult::error));
        }else{
            return LocaleUtils
                .currentReactive()
                .flatMap(locale -> {
                    return organizationService.findByIdName(orgEntity.getName() ,orgEntity.getId())
                                           .map(i -> ValidationResult.error(LocaleUtils.resolveMessage(
                                               "error.orgname_already_exist",
                                               locale,
                                               "单位名称" + orgEntity.getName() + "已存在", orgEntity.getName()))
                                           );
                })
                .defaultIfEmpty(ValidationResult.success())
                .onErrorResume(ValidationException.class,
                               e -> e.getLocalizedMessageReactive().map(ValidationResult::error));
        }

    }

    @PostMapping("/phone/_validate")
    @Authorize(merge = false)
    @Operation(summary = "组织名称验证")
    public Mono<ValidationResult> orgPhoneValidate(@RequestBody(required = true) OrganizationEntity orgEntity) {

        if(orgEntity.getId()!=null && orgEntity.getId().isEmpty()){
            return LocaleUtils
                .currentReactive()
                .flatMap(locale -> {
                    return organizationService.findByPhone(orgEntity.getContactPhone())
                                              .map(i -> ValidationResult.error(LocaleUtils.resolveMessage(
                                                  "error.ContactPhone_already_exist",
                                                  locale,
                                                  "手机号" + orgEntity.getContactPhone() + "已存在", orgEntity.getContactPhone() ))
                                              );
                })
                .defaultIfEmpty(ValidationResult.success())
                .onErrorResume(ValidationException.class,
                               e -> e.getLocalizedMessageReactive().map(ValidationResult::error));
        }else{
            return LocaleUtils
                .currentReactive()
                .flatMap(locale -> {
                    return organizationService.findByPhone(orgEntity.getContactPhone() ,orgEntity.getId())
                                              .map(i -> ValidationResult.error(LocaleUtils.resolveMessage(
                                                  "error.ContactPhone_already_exist",
                                                  locale,
                                                  "手机号" + orgEntity.getContactPhone() + "已存在", orgEntity.getContactPhone()))
                                              );
                })
                .defaultIfEmpty(ValidationResult.success())
                .onErrorResume(ValidationException.class,
                               e -> e.getLocalizedMessageReactive().map(ValidationResult::error));
        }

    }

    /**
     * 查询单位对应的apikey【后端查看使用】
     */
    @GetMapping("/queryOrgAPiKey")
    @Operation(summary = "查询单位还未绑定的设备列表【后端绑定用】")
    public Mono<OrganizationEntity> queryDeviceNoRelate(@Parameter String orgId) {

        return organizationService.queryApiKeyByOrgId(orgId);
    }

}
